home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_087 / id-handler / id-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  7KB  |  295 lines

  1. /****************************************************************************
  2. **  File:       ID-handler.c
  3. **  Program:    ID-handler - an AmigaDOS handler for generating unique names
  4. **  Version:    1.0
  5. **  Author:     Ed Puckett      qix@mit-oz
  6. **
  7. **  Copyright 1987 EpAc Software.  All Rights Reserved.
  8. **
  9. **  History:    02-Feb-87       Original Version
  10. */
  11.  
  12. #include   <libraries/dos.h>
  13. #include   <libraries/dosextens.h>
  14. #include   <libraries/filehandler.h>
  15. #include   <exec/exec.h>
  16. #include   <ctype.h>
  17.  
  18.  
  19.  
  20. /*---------------------------------------------------------------------------
  21. ** References to system
  22. */
  23.  
  24. extern struct Library     *OpenLibrary ();
  25. extern void               CloseLibrary ();
  26. extern struct Task        *FindTask ();
  27. extern ULONG              Wait ();
  28. extern struct Message     *GetMsg ();
  29. extern void               PutMsg ();
  30. extern BYTE               *AllocMem ();
  31. extern void               FreeMem ();
  32.  
  33. extern struct Library     *AbsExecBase;
  34.  
  35.  
  36.  
  37. /*---------------------------------------------------------------------------
  38. ** These are new to the 1.2 release
  39. */
  40.  
  41. #ifndef MODE_READWRITE
  42. # define   MODE_READWRITE   1004
  43. #endif  MODE_READWRITE
  44.  
  45. #ifndef MODE_READONLY
  46. # define   MODE_READONLY    MODE_OLDFILE
  47. #endif  MODE_READONLY
  48.  
  49. #ifndef ACTION_END
  50. # define   ACTION_END       1007     /* not really new, just missing */
  51. #endif  ACTION_END
  52.  
  53.  
  54.  
  55. /*---------------------------------------------------------------------------
  56. */
  57.  
  58. #define   ALLOCMEM_FLAGS    MEMF_PUBLIC
  59.  
  60.  
  61. #define   ID_DIGITS   16
  62.  
  63. typedef struct opendata
  64.   { char   id[ID_DIGITS];
  65.     UBYTE  pos;
  66.   }
  67. OPENDATA;
  68.  
  69.  
  70. struct Library  *SysBase  =  NULL;
  71. struct Library  *DOSBase  =  NULL;
  72.  
  73. static char  ID[ID_DIGITS];
  74.  
  75.  
  76.  
  77. /*---------------------------------------------------------------------------
  78. */
  79.  
  80. #define   BPTRtoCptr(Bp)      ((char *) ((ULONG) (Bp) << 2))
  81. #define   CptrtoBPTR(Cp)      ((BPTR)   ((ULONG) (Cp) >> 2))
  82.  
  83. #define   ReplyPkt(pkt)       PutMsg ((pkt)->dp_Port, (pkt)->dp_Link)
  84.  
  85.  
  86.  
  87. /*---------------------------------------------------------------------------
  88. **      handler() performs initialization, replies to startup packet, and
  89. ** dispatches incoming request packets to the apropriate functions.
  90. **      Our DeviceNode Task field is patched with our process ID so that this
  91. ** process is used for subsequent handler requests.  The function exits only
  92. ** if there is some initialization error.
  93. */
  94.  
  95. void  handler (StartPkt)
  96.  
  97. struct DosPacket  *StartPkt;
  98.  
  99. { struct Task        *Task;
  100.   struct MsgPort     *IDPort;
  101.   ULONG              WakeupMask, SigMask;
  102.   struct DeviceNode  *DevNode;
  103.   struct DosPacket   *pkt, *GetPkt();
  104.   unsigned           i;
  105.   void               OpenID(), CloseID(), ReadID();
  106.  
  107.  
  108.   SysBase= AbsExecBase;
  109.   if ((DOSBase= OpenLibrary (DOSNAME, 0)) == NULL)
  110.     goto QUIT;
  111.  
  112.   Task= FindTask (0);
  113.   IDPort= (struct MsgPort *) ((ULONG) Task + sizeof (struct Task));
  114.   ((struct Process *) Task)->pr_CurrentDir= 0;     /* initial file system root */
  115.  
  116.   WakeupMask= (1L << IDPort->mp_SigBit);
  117.  
  118.   DevNode= (struct DeviceNode *) BPTRtoCptr (StartPkt->dp_Arg3);
  119.   DevNode->dn_Task= IDPort;
  120.  
  121.   ReplyPkt (StartPkt);
  122.  
  123.  
  124.   for (i= 0; i < ID_DIGITS; ++i)
  125.     ID[i]= '0';
  126.  
  127.  
  128. LOOP:
  129.   SigMask= Wait (WakeupMask);
  130.  
  131.   if (SigMask & WakeupMask)
  132.     while ((pkt= GetPkt (IDPort)) != NULL)
  133.       switch (pkt->dp_Type)
  134.         { case MODE_READWRITE:
  135.             OpenID (pkt);
  136.             break;
  137.  
  138.           case MODE_NEWFILE:     /* syn: ACTION_FINDOUTPUT */
  139.             pkt->dp_Res1= 0;
  140.             pkt->dp_Res2= ERROR_WRITE_PROTECTED;
  141.             ReplyPkt (pkt);
  142.             break;
  143.  
  144.           case MODE_READONLY:     /* syn: MODE_OLDFILE, ACTION_FINDINPUT */
  145.             OpenID (pkt);
  146.             break;
  147.  
  148.           case ACTION_END:
  149.             CloseID (pkt);
  150.             break;
  151.  
  152.           case ACTION_READ:
  153.             ReadID (pkt);
  154.             break;
  155.  
  156.           case ACTION_WRITE:
  157.             pkt->dp_Res1= -1;
  158.             pkt->dp_Res2= ERROR_WRITE_PROTECTED;
  159.             ReplyPkt (pkt);
  160.             break;
  161.  
  162.           default:
  163.             pkt->dp_Res1= 0;
  164.             pkt->dp_Res2= ERROR_ACTION_NOT_KNOWN;
  165.             ReplyPkt (pkt);
  166.         }
  167.  
  168.   goto LOOP;
  169.  
  170.  
  171. QUIT:
  172.   DevNode->dn_Task= NULL;     /* bad if someone in process of accessing us . . . */
  173.  
  174.   if (DOSBase != NULL)
  175.     CloseLibrary (DOSBase);
  176. }
  177.  
  178.  
  179.  
  180. /*---------------------------------------------------------------------------
  181. **      GetPkt() returns the DosPacket associated with the next message on
  182. ** "port", or NULL if the port is empty.  The message is removed from the
  183. ** port.  A related macro, ReplyPkt(), is provided above.
  184. */
  185.  
  186. static struct DosPacket  *GetPkt (port)
  187.  
  188. register struct MsgPort  *port;
  189.  
  190. { register struct Message  *msg;
  191.  
  192.   return  ((msg= GetMsg (port)) == NULL)
  193.             ? NULL
  194.             : (struct DosPacket *) msg->mn_Node.ln_Name;
  195. }
  196.  
  197.  
  198.  
  199. /*---------------------------------------------------------------------------
  200. */
  201.  
  202. static void  OpenID (pkt)
  203.  
  204. struct DosPacket  *pkt;
  205.  
  206. { struct FileHandle  *handle;
  207.   OPENDATA           *OpenData  =  NULL;
  208.   unsigned           i;
  209.   void               NextID();
  210.  
  211.  
  212.   if ((OpenData= (OPENDATA *) AllocMem (sizeof (OPENDATA), ALLOCMEM_FLAGS)) == NULL)
  213.     { pkt->dp_Res1= 0;
  214.       pkt->dp_Res2= ERROR_NO_FREE_STORE;
  215.       ReplyPkt (pkt);
  216.     }
  217.  
  218.   for (i= 0; i < ID_DIGITS; ++i)
  219.     OpenData->id[i]= ID[i];
  220.  
  221.   OpenData->pos= 0;
  222.  
  223.   NextID ();
  224.  
  225.   handle= (struct FileHandle *) BPTRtoCptr (pkt->dp_Arg1);
  226.   handle->fh_Arg1= (LONG) OpenData;     /* for identification on Read, Close */
  227.  
  228.   pkt->dp_Res1= 1;
  229.   pkt->dp_Res2= 0;     /* for successful open */
  230.   ReplyPkt (pkt);
  231. }
  232.  
  233.  
  234.  
  235. /*---------------------------------------------------------------------------
  236. */
  237.  
  238. static void  CloseID (pkt)
  239.  
  240. struct DosPacket  *pkt;
  241.  
  242. { OPENDATA  *OpenData;
  243.  
  244.  
  245.   OpenData= (OPENDATA *) pkt->dp_Arg1;
  246.  
  247.   FreeMem (OpenData, sizeof (OPENDATA));
  248.  
  249.   pkt->dp_Res1= 1;
  250.   pkt->dp_Res2= 0;
  251.   ReplyPkt (pkt);
  252. }
  253.  
  254.  
  255.  
  256. /*---------------------------------------------------------------------------
  257. */
  258.  
  259. static void  ReadID (pkt)
  260.  
  261. struct DosPacket  *pkt;
  262.  
  263. { OPENDATA  *OpenData;
  264.   unsigned  n;
  265.  
  266.  
  267.   OpenData= (OPENDATA *) pkt->dp_Arg1;
  268.  
  269.   pkt->dp_Res1= 0;
  270.  
  271.   if (OpenData->pos < ID_DIGITS)
  272.     { if ((n= pkt->dp_Arg3) > (ID_DIGITS - OpenData->pos))
  273.         n= (ID_DIGITS - OpenData->pos);
  274.  
  275.       for ( ; pkt->dp_Res1 < n; ++(pkt->dp_Res1), ++(OpenData->pos))
  276.         ((char *) pkt->dp_Arg2)[pkt->dp_Res1]= OpenData->id[OpenData->pos];
  277.     }
  278.  
  279.   pkt->dp_Res2= 0;
  280.   ReplyPkt (pkt);
  281. }
  282.  
  283.  
  284.  
  285. /*---------------------------------------------------------------------------
  286. */
  287.  
  288. static void  NextID ()
  289.  
  290. { int  i;
  291.  
  292.   for (i= ID_DIGITS - 1; (i >= 0) && (++(ID[i]) > '9'); --i)
  293.     ID[i]= '0';
  294. }
  295.